package asn.match.security;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.mapsengine.MapsEngine;
import com.google.api.services.mapsengine.MapsEngineRequestInitializer;
import com.google.api.services.mapsengine.model.Feature;
import com.google.api.services.mapsengine.model.FeaturesListResponse;
import com.google.api.services.mapsengine.model.GeoJsonPoint;

import asn.match.service.MemberAccountService;

public class MyUtils {

	@Autowired
	private SessionFactory sessionFactory;

	private static final String CHAR_LIST = 
			"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
	private static final int RANDOM_STRING_LENGTH = 10;

	/**
	 * This method generates random string
	 * @return
	 */
	public static String generateUniquevalidationCode(MemberAccountService memberAccountService){
		StringBuffer randStr = new StringBuffer();
		for(int i=0; i<RANDOM_STRING_LENGTH; i++){
			int number = getRandomNumber();
			char ch = CHAR_LIST.charAt(number);
			randStr.append(ch);
		}
		String randStrResult = randStr.toString();
		// il faut tester si randStrResult est unique !
		boolean codeExist = memberAccountService.checkValidationCodeExists(randStrResult);
		if (!codeExist){
			return randStrResult;
		}
		return generateUniquevalidationCode(memberAccountService);
	}
	
	/**
	 * This method generates a unique linkname
	 * @return
	 */
	public static String generateUniqueLinkname(MemberAccountService memberAccountService, String fistname, String lastname){
		String linkname = new String();
		for(int i=0; i<1000; i++){
			int number = (int)(Math.random() * ((1000 - 1) + 1));
			linkname = fistname.toLowerCase() + "." + lastname.toLowerCase() + "." + number;
			if(!memberAccountService.checkLinknameExists(linkname)){
				return linkname;
			}
		}
		return null;
	}

	/**
	 * This method generates random numbers
	 * @return int
	 */
	private static int getRandomNumber() {
		int randomInt = 0;
		Random randomGenerator = new Random();
		randomInt = randomGenerator.nextInt(CHAR_LIST.length());
		if (randomInt - 1 == -1) {
			return randomInt;
		} else {
			return randomInt - 1;
		}
	}

	/**
	 * This method verify if the adresse mail is already used
	 * @return
	 */
	public static boolean validateUniqueEmail(MemberAccountService memberAccountService, String email){
		boolean emailExist = memberAccountService.checkEmailExists(email);
		return emailExist;
	}

	/**
	 * This methode return the ip adress of user's machine
	 * @return
	 */
	public static String getIpAddress(){
		try {
			return InetAddress.getLocalHost().getHostAddress();
		}
		catch(UnknownHostException e){
			System.out.println("UnknowHost");
			return null;
		}
	}
	
	/**
	 * Get client ip address
	 * @return
	 */
	public static String getIpAddress(HttpServletRequest request) {
		String ip = request.getHeader("X-Real-IP");
		if (null != ip && !"".equals(ip.trim())
				&& !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getHeader("X-Forwarded-For");
		if (null != ip && !"".equals(ip.trim())
				&& !"unknown".equalsIgnoreCase(ip)) {
			// get first ip from proxy ip
			int index = ip.indexOf(',');
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		}
		return request.getRemoteAddr();
	}

	/**
	 * This method help us to get gelocalisation informations (longitude, latitude, city, region, country..)
	 * google maps geolocation api is not free (4$ for 1000 request), don't use it for the moment
	 */
	public static Map<String,String> getGeolocalisationInfosByGoogleMaps(){
		Map<String,String> maMap = new HashMap<String, String>();
		String SAMPLE_TABLE_ID = "12421761926155747447-06672618218968397709";
		String PUBLIC_API_KEY = "AIzaSyByjylkQ-8vjh3fDTNO6Z8X5x17fnAomdw";

		HttpTransport transport = new NetHttpTransport();
		JsonFactory jsonFactory = new GsonFactory();

		// This request initializer will ensure the API key is sent with every HTTP request.
		MapsEngineRequestInitializer apiKeyInitializer =
				new MapsEngineRequestInitializer(PUBLIC_API_KEY);

		MapsEngine engine = new MapsEngine.Builder(transport, jsonFactory, null)
		.setMapsEngineRequestInitializer(apiKeyInitializer)
		.setApplicationName("Google-MapsEngineSample/1.0")
		.build();

		FeaturesListResponse featResp;
		try {
			featResp = engine.tables().features().list(SAMPLE_TABLE_ID)
					.setVersion("published")
					.setWhere("State='WA' AND ST_DISTANCE(geometry,ST_POINT(115.8589,-31.9522)) < 100000")
					.execute();
			for (Feature feat : featResp.getFeatures()) {
				System.out.println(
						"Properties: " + feat.getProperties().toString() + "\n\t" +
								"Name: " + feat.getProperties().get("Fcilty_nam") + "\n\t" +
								"Geometry Type: " + feat.getGeometry().getType());

				if (feat.getGeometry() instanceof GeoJsonPoint)  {
					GeoJsonPoint point = (GeoJsonPoint) feat.getGeometry();
					System.out.println("\t" +
							"Longitude: " + point.getCoordinates().get(0) + ", " +
							"Latitude: " +  point.getCoordinates().get(1));
				} else {
					System.out.println("Only points are expected in this table!");
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return maMap;
	}

}
